﻿#include "OiPCH.hpp"
#include <QSettings>

namespace Oi
{
    namespace PLScannerCore
    {
        QString getAppDir()
        {
        #ifdef _WIN32
            wchar_t appPath[512];
            if(GetModuleFileName(NULL, appPath, 512) <= 0)
            {
                return "";
            }
            else
            {
                return QDir::toNativeSeparators(QFileInfo(QString::fromWCharArray(appPath)).absolutePath());
            }
        #else
            char appProc[20];
            char appPath[1024] = { 0 };
            sprintf(appProc, "/proc/%d/exe", getpid());
            readlink(appProc, appPath, 1024);
            return QDir::toNativeSeparators(QFileInfo(appPath).absolutePath());
        #endif
        }
        /**
* @func:    FindFile
* @brief:   查找某个目录下特定类型的文件
* @author:  XXX 2020
* @param:   strFilePath:要搜索的文件夹
            strNameFilters:要搜索的文件类型（例如"*.xml"）
* @return:  符合的文件列表
*/
        QFileInfoList PLScanner::FindFile(const QString& strFilePath, const QString& strNameFilters)
        {
            QFileInfoList fileList;
            if (strFilePath.isEmpty() || strNameFilters.isEmpty())
            {
                return fileList;
            }

            QDir dir;
            QStringList filters;
            filters << strNameFilters;
            dir.setPath(strFilePath);
            dir.setNameFilters(filters);
            QDirIterator iter(dir, QDirIterator::Subdirectories);
            while (iter.hasNext())
            {
                iter.next();
                QFileInfo info = iter.fileInfo();
                if (info.isFile())
                {
                    fileList.append(info);
                }
            }
            return fileList;
        }

        void PLScanner::init()
        {
            auto settings = Core::OiSettings();

            modbusTcp_Addr = settings->value("ModbusTcp/Address", "192.168.10.1").toString();
            modbusTcp_Port = settings->value("ModbusTcp/Port", "502").toString();
            modbusTcp_Name = modbusTcp_Addr + ":" + modbusTcp_Port;

            rootDir = Core::OiGetPermanentDir(RootDir).replace("\\", "/");
            projectDir = Core::OiGetPermanentDir(ProjectDir).replace("\\", "/");
            imgDir = rootDir + "/images";
            productDefaultDir = rootDir + "/product";
            productDir = settings->value("Dir/ProductDir", productDefaultDir).toString();
            recordDir = settings->value("Dir/RecordDir", rootDir + "/record").toString();
            excelTimer = settings->value("Dir/excelTimer",9).toInt();
            excelDir = settings->value("Dir/ExcelDir", rootDir + "/excel").toString();
            dataDir = settings->value("Dir/DataDir", rootDir + "/data").toString();
            correctedDataDir = settings->value("Dir/CorrectedDataDir", rootDir + "/correctData").toString();

            acquireVel = settings->value("Acquire/Vel", 100.0).toDouble();
            acquireDir = settings->value("Acquire/Dir", true).toBool();
            dataOptionDir = settings->value("Acquire/dataOptionDir", 0).toInt();
            captureTimeout = settings->value("Acquire/CaptureTimeout", 20).toInt();
            sideLen = settings->value("Acquire/SideLen", 30.0).toDouble();
            pointMeasureInterval = settings->value("Acquire/PointMeasureInterval", 0.1).toDouble();
            zeroMethod = settings->value("Acquire/ZeroMethod", 0).toInt();
            resolution = settings->value("Acquire/Resolution", 0.1).toDouble();       
            wideCalibEnable = settings->value("Calib/WideCalibEnable", true).toBool();
            saveCorrectedData = settings->value("Calib/SaveCorrectedData", false).toBool();

            QByteArray pBA = settings->value("Calib/WideCalib-P").value<QByteArray>();
            QDataStream pDS(&pBA, QIODevice::ReadOnly);
            pDS >> wideCalib_P;

            if (wideCalib_P.isEmpty())
            {
                wideCalib_P = loadCSV("WideCalib-P.csv");
            }

            measureOffsetY = settings->value("Measure/Offset", 0.0).toDouble();
            measureOffsetY_S = settings->value("Measure/Offset_S", 0.0).toDouble();
            measureOffsetX1 = settings->value("Measure/OffsetX1", 0.0).toDouble();
            measureOffsetX2 = settings->value("Measure/OffsetX2", 0.0).toDouble();
            measureOffsetX = settings->value("Measure/OffsetX", 0.0).toDouble();
            measureOpOffset = settings->value("Measure/opOffset", 0.0).toDouble();
            measureOsOffset = settings->value("Measure/osOffset", 0.0).toDouble();
            measureMidOffset = settings->value("Measure/midOffset", 0.0).toDouble();
            measureDsOffset = settings->value("Measure/dsOffset", 0.0).toDouble();
            measureDrOffset = settings->value("Measure/drOffset", 0.0).toDouble();
            widthHide = settings->value("Measure/WidthHide", 0).toInt();
            sideCorrect = settings->value("Measure/SideCorrect", true).toBool();
            filter = settings->value("Measure/Filter", false).toBool();
            filterLen = settings->value("Measure/FilterLen", 30).toInt();

            thicknessWTDefault = settings->value("Measure/ThicknessWTDefault", 0.03).toDouble();
            thicknessETDefault = settings->value("Measure/ThicknessETDefault", 0.05).toDouble();
            midThicknessWTDefault = settings->value("Measure/ThicknessWTDefault", 0.03).toDouble();
            midThicknessETDefault = settings->value("Measure/MidThicknessETDefault", 0.03).toDouble();
            widthWTDefault = settings->value("Measure/WidthWTDefault", 3.0).toDouble();
            widthETDefault = settings->value("Measure/WidthETDefault", 5.0).toDouble();
            widthFakeRange = settings->value("Measure/widthFakeRange", 20).toDouble();
            widthFakeRatio = settings->value("Measure/widthFakeRatio", 0.9).toDouble();
            widthRatio = settings->value("Measure/widthRatio", 0.915).toDouble();
            edgeThickness = settings->value("Measure/EdgeThickness", 1.0).toDouble();

            elWidthOption = settings->value("Measure/ElWidthOption", 1).toInt();
            profileDispalyOption = settings->value("Measure/ProfileDispalyOption", 0xFFFF).toInt();

            paramMode = settings->value("Params/Mode", 2).toInt();
            switchDelayStopTime = settings->value("Params/SwitchDelayStopTime", 0).toDouble();
            switchDelayStartTime = settings->value("Params/SwitchDelayStartTime", 0).toDouble();

            measureAcqPointMethod = settings->value("Measure/MeasureAcqPointMethod", 1).toInt();
            measureAcqPointLen = settings->value("Measure/MeasureAcqPointLen", 1.0).toInt();
            localDataDir = "plscanner_ha.db";

            if(!QDir(productDir).exists())
            {
                QDir().mkpath(productDir);
            }

            if(!QDir(dataDir).exists())
            {
                QDir().mkpath(dataDir);
            }

            if(!QDir(recordDir).exists())
            {
                QDir().mkpath(recordDir);
            }

            if(!QDir(excelDir).exists())
            {
                QDir().mkpath(excelDir);
            }

            if (!QDir(correctedDataDir).exists())
            {
                QDir().mkpath(correctedDataDir);
            }

            company = "Fobond";
            companyLocal = "ShangHai";
            companyType = "CO., LTD.";
            softName = "PLScanner";
            softVersion = "1.0.0";
            manual = "help.pdf";
            icon = "icon.png";
            companyLogo = "companyIcon.png";
            companyBanner = "companyBanner.png";
            themeName = settings->theme();

            loadOEM();
            simulation = settings->value("Simulation", false).toBool();
            running = settings->value("Start", false).toBool();
            debugging = settings->value("Debug", false).toBool();
            
        #ifdef _DEBUG
            simulation = true;
            super = true;
            admin = true;
            debugging = true;

        #else


            //simulation = true;
            //super = true;
            //admin = true;
            //debugging = true;

            super = false;
            admin = false;
        #endif // _DEBUG
        }

        void PLScanner::exit()
        {
            auto settings = Core::OiSettings();

            settings->setValue("ModbusTcp/Address", modbusTcp_Addr);
            settings->setValue("ModbusTcp/Port", modbusTcp_Port);

            settings->setValue("Dir/ProductDir", productDir);
            settings->setValue("Dir/CurveDir", dataDir);
            settings->setValue("Dir/ExcelDir", excelDir);
            settings->setValue("Dir/RecordDir", recordDir);
            settings->setValue("Dir/excelTimer", excelTimer);
            settings->setValue("Dir/CorrectedDataDir", correctedDataDir);

            settings->setValue("Acquire/Vel", acquireVel);
            settings->setValue("Acquire/Dir", acquireDir);
            settings->setValue("Acquire/dataOptionDir", dataOptionDir);
            settings->setValue("Acquire/CaptureTimeout", captureTimeout);
            settings->setValue("Acquire/SideLen", sideLen);
            settings->setValue("Acquire/PointMeasureInterval", pointMeasureInterval);
            settings->setValue("Acquire/ZeroMethod", zeroMethod);
            settings->setValue("Acquire/Resolution", resolution);

            settings->setValue("Calib/WideCalibEnable", wideCalibEnable);
            settings->setValue("Calib/SaveCorrectedData", saveCorrectedData);

//             QByteArray pBA;
//             QDataStream pDS(&pBA, QIODevice::WriteOnly);
//             pDS << wideCalib_P;
            settings->setValue("Calib/WideCalib-P", "");
            saveCSV("WideCalib-P.csv", wideCalib_P);

            settings->setValue("Measure/Offset", measureOffsetY);
            settings->setValue("Measure/Offset_S", measureOffsetY_S);
            settings->setValue("Measure/OffsetX1", measureOffsetX1);
            settings->setValue("Measure/OffsetX2", measureOffsetX2);
            settings->setValue("Measure/OffsetX", measureOffsetX);
            settings->setValue("Measure/opOffset", measureOpOffset);
            settings->setValue("Measure/osOffset", measureOsOffset);
            settings->setValue("Measure/midOffset", measureMidOffset);
            settings->setValue("Measure/dsOffset", measureDsOffset);
            settings->setValue("Measure/drOffset", measureDrOffset);
            settings->setValue("Measure/WidthHide", widthHide);
            settings->setValue("Measure/SideCorrect", sideCorrect);
            settings->setValue("Measure/Filter", filter);
            settings->setValue("Measure/FilterLen", filterLen);
            settings->setValue("Measure/ElWidthOption", elWidthOption);

            settings->setValue("Measure/ThicknessWTDefault", thicknessWTDefault);
            settings->setValue("Measure/ThicknessETDefault", thicknessETDefault);
            settings->setValue("Measure/MidThicknessWTDefault", midThicknessWTDefault);
            settings->setValue("Measure/MidThicknessETDefault", midThicknessETDefault);
            settings->setValue("Measure/WidthWTDefault", widthWTDefault);
            settings->setValue("Measure/WidthETDefault", widthETDefault);
            settings->setValue("Measure/widthRatio", widthRatio);
            settings->setValue("Measure/EdgeThickness", edgeThickness);
            settings->setValue("Measure/ProfileDispalyOption", profileDispalyOption);

            settings->setValue("Params/Mode", paramMode);
            settings->setValue("Params/SwitchDelayStopTime", switchDelayStopTime);
            settings->setValue("Params/SwitchDelayStartTime", switchDelayStartTime);

            settings->setValue("Measure/MeasureAcqPointMethod", measureAcqPointMethod);
            settings->setValue("Measure/MeasureAcqPointLen", measureAcqPointLen);

            settings->sync();
        }

        void PLScanner::loadOEM()
        {
            QSettings settings(rootDir + "/pls_agent", QSettings::IniFormat);

            company = settings.value("Company", company).toString();
            companyLocal = settings.value("CompanyLocal", companyLocal).toString();
            companyType = settings.value("CompanyType", companyType).toString();
            softName = settings.value("SoftName", softName).toString();
            softVersion = settings.value("SoftVersion", softVersion).toString();
            manual = settings.value("Manual", manual).toString();
            companyLogo = settings.value("CompanyLogo", companyLogo).toString();
            icon = settings.value("Icon", icon).toString();
            companyBanner = settings.value("CompanyBanner", companyBanner).toString();
            themeName = settings.value("Theme", themeName).toString();
            resourceName = settings.value("Resource").toString();
        }

        QList<QPointF> PLScanner::loadCSV(QString fileName)
        {
            QList<QPointF> ps;

            QFile file(fileName);
            if (!file.open(QIODevice::ReadOnly))
            {
                return ps;
            }

            QTextStream in(&file);

            if (in.atEnd())
            {
                file.close();
                return ps;
            }

            QString fileLine = in.readLine();

            QStringList linelist = fileLine.split(",");

            if (linelist.size() < 2 || linelist[0] != "X" && linelist[1] != "Y")
            {
                file.close();
                return ps;
            }

            while (!in.atEnd())
            {
                fileLine = in.readLine();
                linelist = fileLine.split(",");

                if (linelist.size() >= 2)
                {
                    ps.append(QPointF(linelist[0].toDouble(), linelist[1].toDouble()));
                }

            }

            file.close();
            return ps;
        }

        void PLScanner::saveCSV(QString fileName, QList<QPointF> ps)
        {
            QFile file(fileName);
            if (!file.open(QIODevice::WriteOnly))
            {
                return;
            }

            file.write("X,Y\n");

            for (auto p : ps)
            {
                file.write(QString("%1,%2\n").arg(p.x(), 0, 'f', 2).arg(p.y(), 0, 'f', 2).toLocal8Bit());
            }

            file.close();
        }

        void PLScanner::saveCalibRecord(double temp1, double temp2,double value)
        {
            QFile file("CalibRecord.csv");
            if (!file.open(QIODevice::ReadWrite | QIODevice::Append))
            {
                return;
            }

            file.write(QString("%1,%2,%3,%4\n").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).arg(temp1, 0, 'f', 2).arg(temp2, 0, 'f', 2).arg(value, 0, 'f', 4).toLocal8Bit());

            file.close();
        }

        QString PLScanner::OiCompanyName()
        {
            QSettings settings(getAppDir().replace("\\", "/") + "/pls_agent", QSettings::IniFormat);

            return settings.value("Company", "FoBond").toString();
        }

        QString PLScanner::OiSoftName()
        {
            QSettings settings(getAppDir().replace("\\", "/") + "/pls_agent", QSettings::IniFormat);

            return settings.value("SoftName", "PLScanner").toString();
        }

        PLScanner* PLScanner::instance()
        {
            static PLScanner s_sliceBalance; return &s_sliceBalance;
        }
    }
}
